package com;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import model.TableData;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class dataToHtml implements Serializable {

    private final static String sp = File.separator;

    private final static int table2Max = 50;

    private static Map<? extends String, ? extends String> makePngHtml(ArrayList<String> htmlPictures, String s, int k) {
        HashMap<String, String> result = new HashMap<>();
        StringBuilder str = new StringBuilder();
        for (int a = 0; a < k; a++) {
            str.append("../");
        }
        String path = parentDirectoryPath(htmlPictures.get(0)) + sp + new File(htmlPictures.get(0)).getName() + "s.html";
        List<String> pictures = new ArrayList<>();
        for (String s1 : htmlPictures) {
            String[] split = s1.split("res");
            StringBuilder pp = new StringBuilder(split[1].substring(1));
            int ll = pp.toString().replace(sp, "/").split("/").length - 1;
            for (int j = 0; j < ll; j++) {
                pp.insert(0, "../");
            }
            pictures.add(pp.toString());
        }
        try {
            String jarPath = new fly().getJarPath();
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDirectoryForTemplateLoading(new File(jarPath + sp + "ftl"));
            configuration.setDefaultEncoding("UTF-8");
            Template template = configuration.getTemplate("pngS.ftl");
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(path)), StandardCharsets.UTF_8));
            HashMap<String, Object> map = new HashMap<>();
            map.put("path", str.toString());
            map.put("pictures", pictures);
            map.put("first", pictures.get(0));
            template.process(map, writer);
            writer.flush();
            writer.close();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
        result.put(s, path);
        return result;
    }

    /*基础表格html*/
    private static String tableBaseHtml(TableData tableData, String path, int k, int type) {
        String jarPath = new fly().getJarPath();
        if (type == 5) {
            path = path + "2.html";
        } else {
            path = path + ".html";
        }
        try {
            Configuration configuration = new Configuration(Configuration.getVersion());
            configuration.setDirectoryForTemplateLoading(new File(jarPath + sp + "ftl"));

            configuration.setDefaultEncoding("UTF-8");
            HashMap<Integer, String> typeMap = new HashMap<>();
            typeMap.put(1, "table_base" + ".ftl");
            typeMap.put(2, "table_base2" + ".ftl");
            typeMap.put(3, "table_base3" + ".ftl");
            typeMap.put(4, "table_base4" + ".ftl");
            typeMap.put(5, "table_base5" + ".ftl");
            typeMap.put(6, "html" + ".ftl");
            typeMap.put(7, "table_base" + ".ftl");
            typeMap.put(8, "table_base3" + ".ftl");
            typeMap.put(9, "table_base9" + ".ftl");
            typeMap.put(10, "table_base" + ".ftl");
            typeMap.put(11, "table_base11" + ".ftl");
            Template template = configuration.getTemplate(typeMap.get(type));
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(path)), StandardCharsets.UTF_8));
            HashMap<String, Object> map = new HashMap<>();
            map.put("table", tableData);
            StringBuilder str = new StringBuilder();
            for (int a = 0; a < k; a++) {
                str.append("../");
            }
            map.put("path", str.toString());
            template.process(map, writer);
            writer.flush();
            writer.close();
            return (path);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static HashMap<String, String> becomeHtml(String packagePath) {
        /*获得配置文件路径*/
        String propertiesPath = new fly().getJarPath() + sp + "config" + sp + "keyValue.properties";

        /*配置文件变map信息*/
        HashMap<String, String> keyValueMap = getKey(propertiesPath);


        return toPdfAndHtml(packagePath, keyValueMap);

    }

    private static HashMap<String, String> toPdfAndHtml(String packagePath, HashMap<String, String> keyValueMap) {
        HashMap<String, String> result = new HashMap<>();
        packagePath = packagePath + sp;
        /*第一部分 a OTU聚类与物种注释*/
        String a1 = keyValueMap.get("1_1_table_1");

        result.putAll(table_one(a1, packagePath, "1_1_table_1", 1));


        String a2 = keyValueMap.get("1_1_png_2");
        result.putAll(png_base(packagePath, a2, "1_1_png_2"));

        String a3 = keyValueMap.get("1_1_table_3");
        result.putAll(table_one(a3, packagePath, "1_1_table_3", 1));

        String a4 = keyValueMap.get("1_2_table_1");
        result.putAll(table_one(a4, packagePath, "1_2_table_1", 2));

        String a5 = keyValueMap.get("1_3_table_1");
        result.putAll(table_one(a5, packagePath, "1_3_table_1", 3));

        String a6 = keyValueMap.get("2_1_table_1");
        String a6filename = findFileStr(packagePath + a6, "xls");
        result.putAll(table_one(a6 + a6filename, packagePath, "2_1_table_1", 4));
        result.putAll(table_one(a6 + a6filename, packagePath, "2_1_table_2", 5));

        String a8 = keyValueMap.get("2_1_table_3");
        result.putAll(table_one(a8, packagePath, "2_1_table_3", 6));

        String a9 = keyValueMap.get("2_2_table_1");
        String a9filename = findFileStr(packagePath + a9, "xls");
        result.putAll(table_one(a9 + a9filename, packagePath, "2_2_table_1", 7));

        String a10 = keyValueMap.get("2_2_png_2");
        result.putAll(png_base(packagePath, a10, "2_2_png_2"));


        String a11 = keyValueMap.get("2_3_table_1");
        String a11filename = findFileStr(packagePath + a11, "xls");
        result.putAll(table_one(a11 + a11filename, packagePath, "2_3_table_1", 7));

        String a12 = keyValueMap.get("2_3_png_2");
        result.putAll(png_base(packagePath, a12, "2_3_png_2"));

        String a13 = keyValueMap.get("2_4_png_1");
        result.putAll(png_base(packagePath, a13, "2_4_png_1"));

        String a14 = keyValueMap.get("2_5_png_1");
        result.putAll(png_base(packagePath, a14, "2_5_png_1"));

        String a15 = keyValueMap.get("3_1_png_1");
        result.putAll(png_base(packagePath, a15, "3_1_png_1"));

        String a16 = keyValueMap.get("3_2_png_1");
        result.putAll(png_html2(packagePath, a16, "3_2_png_1", "pdf"));

        String a17 = keyValueMap.get("3_3_png_1");
        result.putAll(png_base(packagePath, a17, "3_3_png_1"));

        String a18 = keyValueMap.get("3_4_png_1");
        result.putAll(png_html2(packagePath, a18, "3_4_png_1", "pdf"));

        String a19 = keyValueMap.get("3_5_table_1");
        String a19filename = findFileStr(packagePath + a19, "xls");
        result.putAll(table_one(a19 + a19filename, packagePath, "3_5_table_1", 8));

        String a20 = keyValueMap.get("3_5_png_2");
        result.putAll(png_base(packagePath, a20, "3_5_png_2"));

        String a21 = keyValueMap.get("3_6_png_1");
        result.putAll(png_base(packagePath, a21, "3_6_png_1"));

        String a22 = keyValueMap.get("4_1_png_1");
        result.putAll(png_html2(packagePath, a22, "4_1_png_1", "otu_table.txt.all.pdf"));

        String a23 = keyValueMap.get("4_1_png_2");
        result.putAll(png_html2(packagePath, a23, "4_1_png_2", "Group_Distances.pdf"));

        String a24 = keyValueMap.get("4_2_png_1");
        result.putAll(png_html2(packagePath, a24, "4_2_png_1", "@3d-pca"));

        String a25 = keyValueMap.get("4_2_png_2");
        result.putAll(png_html2(packagePath, a25, "4_2_png_2", "3d-pca"));

        String a26 = keyValueMap.get("4_3_png_1");
        result.putAll(png_html2(packagePath, a26, "4_3_png_1", "@3d-pcoa"));

        String a27 = keyValueMap.get("4_3_png_2");
        result.putAll(png_html2(packagePath, a27, "4_3_png_2", "3d-pcoa"));
        String a28 = keyValueMap.get("4_4_png_1");
        result.putAll(png_html2(packagePath, a28, "4_4_png_1", "@3d-pcoa"));

        String a29 = keyValueMap.get("4_4_png_2");
        result.putAll(png_html2(packagePath, a29, "4_4_png_2", "3d-pcoa"));

        String a30 = keyValueMap.get("4_5_png_1");
        result.putAll(png_html2(packagePath, a30, "4_5_png_1", "pdf"));

        String a31 = keyValueMap.get("4_5_png_2");
        result.putAll(png_html2(packagePath, a31, "4_5_png_2", "pdf"));

        String a32 = keyValueMap.get("4_6_png_1");
        result.putAll(png_html2(packagePath, a32, "4_6_png_1", "pdf"));

        String a33 = keyValueMap.get("4_7_png_1");
        result.putAll(png_html2(packagePath, a33, "4_7_png_1", "pdf"));

        String a34 = keyValueMap.get("4_8_table_1");
        result.putAll(table_one(a34, packagePath, "4_8_table_1", 1));

        String a35 = keyValueMap.get("4_9_table_1");
        result.putAll(table_one(a35, packagePath, "4_9_table_1"));

        String a36 = keyValueMap.get("5_2_table_1");
        result.putAll(table_one(a36, packagePath, "5_2_table_1", 11));

        String a37 = keyValueMap.get("5_3_table_1");
        String a37filename = findFileStr(packagePath + a37, "txt");
        result.putAll(table_one(a37 + a37filename, packagePath, "5_3_table_1", 10));


        return result;
    }


    private static Map<? extends String, ? extends String> png_html2(String packagePath, String a16, String s, String str) {
        ArrayList<String> htmlPictures = new ArrayList<>();
        String[] split = a16.split("@");
        String s3 = split[0];
        s3 = s3.replace("/", sp);
        s3 = s3.replace("\\", sp);
        int k = s3.length() - s3.replace(sp, "").length() + 1;
        for (String s1 : split) {
            File file = new File(packagePath + s1);
            File[] files = file.listFiles();
            if (file.exists() && files != null) {
                for (File f : files) {
                    if (checkTrue(f.getName(), str)) {
                        String resPath = parentDirectoryPath(packagePath) + sp + "web" + sp + "res" + sp + s1 + f.getName();
                        String s2 = pngBase(f.getAbsolutePath(), resPath);
                        htmlPictures.add(s2);
                    }
                }
            }
        }
        if (htmlPictures.size() != 0) {
            return makePngHtml(htmlPictures, s, k);
        } else {
            return new HashMap<>();
        }
    }

    /*判断是否符合*/
    private static boolean checkTrue(String name, String str) {
        if (fileType(name).equals("pdf") || fileType(name).equals("png")) {
            if (str.contains("@")) {
                String ss = str.substring(1);
                return !name.contains(ss);
            } else {
                return name.contains(str);
            }
        }
        return false;
    }

    /*图片的基本处理方法*/
    private static Map<? extends String, ? extends String> png_base(String packagePath, String a2, String s) {
        HashMap<String, String> result = new HashMap<>();
        String a2PngPath = packagePath + a2;
        if (new File(a2PngPath).exists()) {
            String a2htmlPath = parentDirectoryPath(packagePath) + sp + "web" + sp + "res" + sp + a2;
            String s1 = pngBase(a2PngPath, a2htmlPath);
            result.put(s, s1);
            return result;
        }
        return new HashMap<>();
    }

    /*找到路劲下的 什么后缀的文件*/
    private static String findFileStr(String a6, String xls) {
        String xls2 = null;
        if (xls.equals("txt")) {
            xls2 = "xls";
        }
        if (xls.equals("xls")) {
            xls2 = "txt";
        }
        File file = new File(a6);
        File[] files = file.listFiles();
        if (file.exists() && files != null) {
            for (File f : files) {
                if ((f.isFile() && fileType(f.getName()).equals(xls)) || (f.isFile() && fileType(f.getName()).equals(xls2))) {
                    return f.getName();
                }
            }
        }
        return null;
    }


    /*读取基础表格变html*/
    private static TableData readTable_base(String file, int type) {
        if (type != 6) {
            try {
                ArrayList<List<String>> result = new ArrayList<>();

                InputStreamReader fReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
                BufferedReader bb = new BufferedReader(fReader);

                String line;
                while ((line = bb.readLine()) != null) {
                    String[] split = line.split("\t");
                    ArrayList<String> list = new ArrayList<>(Arrays.asList(split));
                    result.add(list);
                }
                fReader.close();
                return getTableData(result);
            } catch (IOException e) {
                System.out.println("--warning :   may be no file " + new File(file).getAbsolutePath());
            }
            return null;
        }
        /*处理html*/
        return htmlData(file);
    }

    /*处理html*/
    private static TableData htmlData(String file) {
        try {
            BufferedReader bb = new BufferedReader(new FileReader(file));
            ArrayList<String> content = new ArrayList<>();
            String line;
            while ((line = bb.readLine()) != null) {
                content.add(line);
            }
            ArrayList<String> oneLine = new ArrayList<>();
            for (int a = 3; a < 8; a++) {
                oneLine.add(content.get(a));
            }
            TableData result = new TableData();
            result.setTableOneLine(oneLine);
            bb.close();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    private static Map<? extends String, ? extends String> table_one(String a1, String packagePath, String key, int type) {
        String a1TablePath = packagePath + a1;
        if (new File(a1TablePath).exists()) {
            String a1htmlPath = parentDirectoryPath(packagePath) + sp + "web" + sp + "res" + sp + a1;
            if (type == 10) {
                changeTable10(a1TablePath);
            }
            if(type==11){
                changeTable11(a1TablePath);
            }
            TableData a1tableData = readTable_base(a1TablePath, type);
            if (a1tableData == null) {
                return null;
            }
            if (type == 2) {
                tableType2(a1tableData);
            }
            if (type == 3) {
                tableType3(a1tableData);
            }
            if (type == 8) {
                tableType8(a1tableData);
            }
            if (type == 7) {
                tableType7(a1tableData);
            }
            if (type == 10) {
                tableType10(a1tableData,type);
            }
            if(type==11){
                tableType10(a1tableData,type);
            }

            a1htmlPath = tableBaseHtml(a1tableData, a1htmlPath, getK(a1htmlPath), type);
            HashMap<String, String> result = new HashMap<>();
            result.put(key, a1htmlPath);
            return result;
        }
        return new HashMap<>();
    }

    private static void changeTable11(String a1TablePath) {
        String rPath = parentDirectoryPath(a1TablePath) + sp + "demo.R";
        rPath = rPath.replace("\\", "/");
        rPath = rPath.replace(sp, "/");
        a1TablePath = a1TablePath.replace("\\", "/");
        a1TablePath = a1TablePath.replace(sp, "/");
        String firstLine ="data <- read.delim('" + a1TablePath +"', check.names = F);"+"data[,2:(ncol(data)-1)] <- round(data[,2:(ncol(data)-1)],3)\n";
        String secondLine ="write.table(file = '" + a1TablePath + "',data,sep='\\t',row.names = F, quote = F)";
        try {
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(rPath)), StandardCharsets.UTF_8));
            writer.write(firstLine);
            writer.write(secondLine);
            writer.close();
            Shell.shell("Rscript " + rPath);
            boolean delete = new File(rPath).delete();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void changeTable10(String a1TablePath) {
        String rPath = parentDirectoryPath(a1TablePath) + sp + "demo.R";
        rPath = rPath.replace("\\", "/");
        rPath = rPath.replace(sp, "/");
        a1TablePath = a1TablePath.replace("\\", "/");
        a1TablePath = a1TablePath.replace(sp, "/");
        String firstLine = "data <- round(read.delim(" + "'" + a1TablePath + "'" + ", check.names = F,row.names = 1),5)\n";
        String secondLine = "write.table(file = '" + a1TablePath + "',data,sep='\\t',col.names=NA, quote = F)";
        try {
            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(rPath)), StandardCharsets.UTF_8));
            writer.write(firstLine);
            writer.write(secondLine);
            writer.close();
            Shell.shell("Rscript " + rPath);
            boolean delete = new File(rPath).delete();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

    }

    private static void tableType10(TableData a1tableData,int type) {
        List<List<String>> tableOtherLine = a1tableData.getTableOtherLine();
        ArrayList<List<String>> lists = new ArrayList<>();
        int l = 0;
        if(type == 10){l = 6;}
        if(type == 11){l = 14;}
        for (int a = 0; a < l; a++) {
            lists.add(tableOtherLine.get(a));
        }
        a1tableData.setTableOtherLine(lists);
    }

    private static Map<? extends String, ? extends String> table_one(String a1, String packagePath, String key) {
        String a1TablePath = packagePath + a1;
        if (new File(a1TablePath).exists()) {
            String a1htmlPath = parentDirectoryPath(packagePath) + sp + "web" + sp + "res" + sp + a1;
            TableData a1tableData = readTxt(a1TablePath);
            String s = tableBaseHtml(a1tableData, a1htmlPath, getK(a1htmlPath), 9);
            HashMap<String, String> result = new HashMap<>();
            result.put(key, s);
            return result;
        }
        return new HashMap<>();
    }

    private static TableData readTxt(String a1TablePath) {
        try {
            ArrayList<List<String>> otherLines = new ArrayList<>();
            InputStreamReader fReader = new InputStreamReader(new FileInputStream(a1TablePath), StandardCharsets.UTF_8);
            BufferedReader bb = new BufferedReader(fReader);
            String Line;
            while ((Line = bb.readLine()) != null) {
                ArrayList<String> strings = new ArrayList<>();
                strings.add(Line);
                otherLines.add(strings);
            }
            TableData tableData = new TableData();
            tableData.setTableOtherLine(otherLines);
            return tableData;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    private static void tableType8(TableData a1tableData) {
        List<String> tableOneLine = a1tableData.getTableOneLine();
        ArrayList<String> bb1 = new ArrayList<>();
        for (int a = 0; a < 6; a++) {
            bb1.add(tableOneLine.get(a));
        }
        bb1.add("...");
        bb1.add(tableOneLine.get(tableOneLine.size() - 1));
        a1tableData.setTableOneLine(bb1);
        List<List<String>> tableOtherLine = a1tableData.getTableOtherLine();
        ArrayList<List<String>> bbo = new ArrayList<>();
        for (int a = 0; a < 1; a++) {
            List<String> oldLine = tableOtherLine.get(a);
            List<String> newLine = new ArrayList<>();
            for (int k = 0; k < 6; k++) {
                newLine.add(oldLine.get(k));
            }
            newLine.add("...");
            newLine.add(oldLine.get(oldLine.size() - 1));
            bbo.add(newLine);
        }
        a1tableData.setTableOtherLine(bbo);
    }

    private static void tableType7(TableData a1tableData) {
        List<List<String>> tableOtherLine = a1tableData.getTableOtherLine();
        List<List<String>> otherLine = new ArrayList<>();
        for (int a = 0; a < table2Max; a++) {
            otherLine.add(tableOtherLine.get(a));
        }
        a1tableData.setTableOtherLine(otherLine);
    }

    /*table的第三种数据转换*/
    private static void tableType3(TableData a1tableData) {
        List<String> tableOneLine = a1tableData.getTableOneLine();
        ArrayList<String> bb1 = new ArrayList<>();
        for (int a = 0; a < 6; a++) {
            bb1.add(tableOneLine.get(a));
        }
        bb1.add("...");
        bb1.add(tableOneLine.get(tableOneLine.size() - 1));
        a1tableData.setTableOneLine(bb1);
        List<List<String>> tableOtherLine = a1tableData.getTableOtherLine();
        ArrayList<List<String>> bbo = new ArrayList<>();
        int size = tableOtherLine.size();
        if (size > table2Max) {
            size = table2Max;
        }
        for (int a = 0; a < size; a++) {
            List<String> oldLine = tableOtherLine.get(a);
            List<String> newLine = new ArrayList<>();
            for (int k = 0; k < 6; k++) {
                newLine.add(oldLine.get(k));
            }
            newLine.add("...");
            newLine.add(oldLine.get(oldLine.size() - 1));
            bbo.add(newLine);
        }
        a1tableData.setTableOtherLine(bbo);
    }

    /*table的第二种数据转换*/
    private static void tableType2(TableData a1tableData) {
        List<String> tableOneLine = a1tableData.getTableOneLine();
        ArrayList<String> bb = new ArrayList<>();
        for (int a = 0; a < 9; a++) {
            if (a != 8) {
                bb.add(tableOneLine.get(a));
            } else {
                bb.add("...");
            }
        }
        a1tableData.setTableOneLine(bb);
        List<List<String>> tableOtherLine = a1tableData.getTableOtherLine();
        ArrayList<List<String>> bbo = new ArrayList<>();
        int size = tableOtherLine.size();
        if (size > table2Max) {
            size = table2Max;
        }
        for (int a = 0; a < size; a++) {
            List<String> oldLine = tableOtherLine.get(a);
            List<String> newLine = new ArrayList<>();
            int size1 = oldLine.size();
            if (size1 >= 26) {
                size1 = 26;
            }
            for (int k = 0; k < size1; k++) {
                if (k != size1 - 1) {
                    newLine.add(oldLine.get(k));
                } else {
                    newLine.add("...");
                }
            }
            bbo.add(newLine);
        }
        a1tableData.setTableOtherLine(bbo);
    }

    /*png的基本操作*/
    private static String pngBase(String a2PngPath, String a2htmlPath) {
        a2PngPath = a2PngPath.replace("/", sp);
        a2PngPath = a2PngPath.replace("\\", sp);
        a2htmlPath = a2htmlPath.replace("/", sp);
        a2htmlPath = a2htmlPath.replace("\\", sp);

        String s = fileType(a2htmlPath);
        if (s.equals("pdf")) {
            PdfToPng.pdfFileToImage(new File(a2PngPath), a2htmlPath + ".png");
        }
        if (s.equals("png")) {
            try {
                FileUtil.copyFile(a2PngPath, a2htmlPath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return a2htmlPath + ".png";
    }

    /*算出里js css 几个层级文件*/
    private static int getK(String a1htmlPath) {
        a1htmlPath = a1htmlPath.split("res")[1];
        a1htmlPath = a1htmlPath.replace("/", sp);
        a1htmlPath = a1htmlPath.replace("\\", sp);
        return (a1htmlPath.length() - a1htmlPath.replace(sp, "").length());
    }

    /*配置文件变map信息*/
    public static HashMap<String, String> getKey(String propertiesPath) {
        Properties properties = new Properties();
        HashMap<String, String> result = new HashMap<>();
        try {
            properties.load(new FileReader(propertiesPath));
            for (String s : properties.stringPropertyNames()) {
                result.put(s, (String) properties.get(s));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }


    public static TableData getTableData(List<List<String>> list) {
        TableData tableData = new TableData();
        tableData.setTableOneLine(list.get(0));
        list.remove(0);
        tableData.setTableOtherLine(list);
        return tableData;
    }

    private static String parentDirectoryPath(String packagePath) {
        return new File(packagePath).getParent();
    }

    public static String fileType(String ss) {
        int i = ss.lastIndexOf(".");
        return ss.substring(i + 1);
    }
}
